package com.hyt.it.ogt.kq.service.gov.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Maps;
import com.hyt.core.base.BaseEntity;
import com.hyt.core.util.UUIDUtils;
import com.hyt.it.ogt.kq.common.config.ConfigManager;
import com.hyt.it.ogt.kq.common.config.exception.KqException;
import com.hyt.it.ogt.kq.common.enums.ArrangeRuleEnum;
import com.hyt.it.ogt.kq.common.enums.SelfArrangeEnum;
import com.hyt.it.ogt.kq.common.gov.constant.*;
import com.hyt.it.ogt.kq.common.gov.utils.GovPage;
import com.hyt.it.ogt.kq.common.gov.utils.HuaweiCloudObsUtil;
import com.hyt.it.ogt.kq.common.gov.utils.StringUtil;
import com.hyt.it.ogt.kq.common.utils.HttpUtil;
import com.hyt.it.ogt.kq.service.gov.arrange.AdmissionService;
import com.hyt.it.ogt.kq.service.gov.den.ArrangedResultExportUtil;
import com.hyt.it.ogt.kq.service.gov.mapper.ArrangeMapper;
import com.hyt.it.ogt.kq.service.gov.mapper.TimeRoomCandidateMapper;
import com.hyt.it.ogt.kq.service.gov.mapper.TimeRoomMapper;
import com.hyt.it.ogt.kq.service.gov.model.dto.ProgressResult;
import com.hyt.it.ogt.kq.service.gov.model.entity.*;
import com.hyt.it.ogt.kq.service.gov.model.param.arrange.*;
import com.hyt.it.ogt.kq.service.gov.model.vo.*;
import com.hyt.it.ogt.kq.service.gov.model.vo.arrange.*;
import com.hyt.it.ogt.kq.service.gov.model.vo.examiner.TimeRoomParamVO;
import com.hyt.it.ogt.kq.service.gov.service.*;
import com.hyt.it.ogt.kq.service.gov.service.obs.CloudObsService;
import com.hyt.it.ogt.kq.service.model.entity.CandidateSubject;
import com.hyt.it.ogt.kq.service.model.entity.Subject;
import com.hyt.it.ogt.kq.service.model.entity.TaskCandidateArea;
import com.hyt.loginfo.service.IUaDeptService;
import com.hyt.model.cloudefile.entity.CloudeFileProjectRecord;
import com.hyt.progress.service.ProgressManager;
import com.linuxense.javadbf.DBFField;
import com.linuxense.javadbf.DBFWriter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.*;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Slf4j
@Service
public class ArrangeServiceImpl implements IArrangeService {
    @Resource
    private ITimeRoomCandidateService iTimeRoomCandidateService;
    @Resource
    private ITimeService iTimeService;
    @Resource
    private ITaskRoomService iTaskRoomService;
    @Resource
    private ITimeRoomService iTimeRoomService;
    @Resource
    private IUaDeptService iUaDeptService;
    @Resource
    private ITimeSubjectService iTimeSubjectService;
    @Resource
    private ITaskAreaService iTaskAreaService;
    @Resource
    private ISubjectService iSubjectService;
    @Resource
    private ICandidateSubjectService iCandidateSubjectService;
    @Resource
    private ArrangeMapper arrangeMapper;
    @Resource
    private ITimeRoomParamService iTimeRoomParamService;
    @Resource
    private ITaskService iTaskService;
    @Resource
    private ITimeRoomExcludeService iTimeRoomExcludeService;
    @Resource
    private TimeRoomMapper timeRoomMapper;
    @Resource
    private TimeRoomCandidateMapper timeRoomCandidateMapper;
    @Resource
    private ITaskPlaceService iTaskPlaceService;
    @Resource
    private AdmissionService admissionService;
    @Resource
    private IProctorService iProctorService;
    @Resource
    private ITaskCandidateAreaService iTaskCandidateAreaService;
    @Resource
    private ICustomArrangeService iCustomArrangeService;
    @Resource
    private ArrangedResultExportUtil arrangedResultExportUtil;
    @Resource
    private IExamResultMonitorService iExamResultMonitorService;
    @Resource
    private ConfigManager configManager;
    @Resource
    CloudObsService cloudObsService;

    @Override
    public ArrangeResultVO getArrangeCountResult(String taskId) {
        ArrangeResultVO resultVO = new ArrangeResultVO();
        // 统计总考场数量
        int roomTotalNum = iTaskRoomService.lambdaQuery().eq(TaskRoom::getTaskId, taskId).eq(BaseEntity::getDelFlag, false).count();
//        int roomTotalNum = arrangeMapper.arrangeRoomCount(taskId, deptSets);

        // 总考场数量
        resultVO.setRoomTotalNum(roomTotalNum);
        // 统计已编排考场
//        resultVO.setRoomNum(arrangeMapper.countArrangedRoomNum(taskId, null));
        resultVO.setRoomNum(timeRoomMapper.countRoomNum(taskId, null));



        // 查询所有批次
        List<Time> timeList = iTimeService.lambdaQuery().eq(Time::getTaskId, taskId).eq(BaseEntity::getDelFlag, false)
                .orderByAsc(Time::getCode).list();
        resultVO.setTimeNum(timeList.size());

        List<ArrangeCountVo> timeCountList = iTimeRoomCandidateService.countCandidateByTime(taskId);

        List<ArrangeCountVo> subjectCountList = iCandidateSubjectService.getCountBySubject(taskId);

        List<TimeSubject> timeSubjectList = iTimeSubjectService.lambdaQuery().select(TimeSubject::getSubjectId,TimeSubject::getTimeId)
                                            .eq(TimeSubject::getTaskId,taskId).eq(BaseEntity::getDelFlag, false).list();

        // 已编排考生总数
        int candidateTotalNum = 0;
        for (Time time : timeList) {
            // 批次总报考考生数量
            //int tsc = iTimeSubjectService.countByTime(taskId, time.getId());
            int tsc = 0;
            List<String> subjectIdList = new ArrayList<>();
            if(CollectionUtil.isNotEmpty(timeSubjectList)){
                for(TimeSubject timeSubject: timeSubjectList){
                    if(time.getId().equals(timeSubject.getTimeId())){
                        subjectIdList.add(timeSubject.getSubjectId());
                    }
                }
            }

            if(CollectionUtil.isNotEmpty(subjectCountList) && CollectionUtil.isNotEmpty(subjectIdList)){
                for(ArrangeCountVo vo : subjectCountList){
                    if(subjectIdList.contains(vo.getSubjectId())){
                        tsc += vo.getNum();
                    }
                }
            }
            // 已编排考生数
            int candidateNum = 0;
            if(CollectionUtil.isNotEmpty(timeCountList)){
                for(ArrangeCountVo vo : timeCountList){
                    if(time.getId().equals(vo.getTimeId())){
                        candidateNum = vo.getNum();
                        break;
                    }
                }
            }

            candidateTotalNum += candidateNum;
            if (candidateNum > 0) {
                // 编排考场数
                int arrangedRoomNum = iTimeRoomCandidateService.lambdaQuery().select(TimeRoomCandidate::getRoomId)
                        .eq(TimeRoomCandidate::getTaskId, taskId)
                        .eq(TimeRoomCandidate::getTimeId, time.getId()).eq(BaseEntity::getDelFlag, false)
                        .groupBy(TimeRoomCandidate::getRoomId).list().size();

                Integer ignoreRoomNum = iTimeRoomExcludeService.lambdaQuery().select(TimeRoomExclude::getTimeId)
                        .eq(TimeRoomExclude::getTaskId, taskId)
                        .eq(TimeRoomExclude::getTimeId, time.getId()).eq(BaseEntity::getDelFlag, false).count();

                resultVO.getTimeCount().add(ArrangeResultCountVO.builder().timeName(time.getName())
                        .arrangedRoomNum(arrangedRoomNum).roomNum(roomTotalNum - ignoreRoomNum - arrangedRoomNum)
                        .arrangedCandidateNum(candidateNum).notArrangedCandidateNum(tsc - candidateNum).build());
            } else {
                resultVO.getTimeCount()
                        .add(ArrangeResultCountVO.builder().timeName(time.getName()).arrangedRoomNum(0).roomNum(0)
                                .arrangedCandidateNum(0).notArrangedCandidateNum(tsc).build());
            }
        }
        resultVO.setCandidateNum(candidateTotalNum);
        resultVO.setArrangeDate(iTaskService.getById(taskId).getArrangeDate());
        return resultVO;
    }

    @Override
    public Page<ArrangeResultByTimeVO> searchArrangeResultByTime(Page<ArrangeResultByTimeVO> page, ArrangeResultByTimeParam param) {
        arrangeMapper.searchArrangeResultByTime(page, param);
        if (CollectionUtils.isNotEmpty(page.getRecords())) {
            page.getRecords().forEach(item -> {
                // 编排考场数
                item.setRoomNum(item.getRoomStr().split(",").length);
                item.setRoomStr(null);
                item.setSubjectNum(item.getSubjectStr().split(",").length);
                item.setSubjectStr(null);
            });
        }
        return page;
    }

    public String JudgeAreaLevel(String taskId){
        String level = "";
        //虚拟考场编排 按考区编排，因为系统所有的编排考生都定位到三级，因此在展示时需要区分按几级编排
        List<TimeRoomParamVO> paramList = iTimeRoomParamService.getTaskTimeRoomParam(taskId);
        Map<String,String> paramMap = Maps.newHashMap();
        paramList.stream().forEach(timeRoomParam -> {
            paramMap.put(timeRoomParam.getCode(),timeRoomParam.getValue());
        });
        String arrangeRule = paramMap.get(StringCodeEnum.ARRANGE_PARAM_ARRANGE_RULE.getCode());
        String arrangeType = paramMap.get(StringCodeEnum.ARRANGE_PARAM_ARRANGE_TYPE.getCode());
        String arrangeSelfLevel = paramMap.get(StringCodeEnum.ARRANGE_SELF_LEVEL.getCode());
        if((String.valueOf(ArrangeParamCodeEnum.ARRANGE_ROOM_TYPE_VIRTUAL.getCode()).equals(arrangeType)
                || String.valueOf(ArrangeParamCodeEnum.ARRANGE_ROOM_TYPE_PHYSICAL.getCode()).equals(arrangeType))
                && String.valueOf(ArrangeRuleEnum.SELF.getCode()).equals(arrangeRule)){
            level = arrangeSelfLevel;
        }
        return level;
    }

    @Override
    public Page<ArrangeResultByRoomVO> searchArrangeResultByRoom(Page<ArrangeResultByRoomVO> page,
                                                                 ArrangeResultByRoomParam param) {
        String level = JudgeAreaLevel(param.getTaskId());
        param.setAreaParentIds(iProctorService.getAreasByAreaId(param.getTaskId(), param.getArea()));
        if(StringUtils.isNotBlank(param.getAreaParentIds())){
            param.setAreaParentIds(param.getAreaParentIds().substring(0,param.getAreaParentIds().length()-1));
        }
        if(StringUtils.isNotBlank(param.getDept())) {
            param.setDeptIds(iProctorService.getAncestorsByDeptId(param.getDept()));
        }
        arrangeMapper.searchArrangeResultByRoom(page, param);
        if (CollectionUtils.isNotEmpty(page.getRecords())) {
            List<String> deptIds = page.getRecords().stream()
                    .filter(s -> Objects.nonNull(s.getDept())).map(ArrangeResultByRoomVO::getDept).collect(Collectors.toList());
            Map<String, String> ancestorsNames = new HashMap<>();
            if(deptIds.size() > 0) {
                ancestorsNames.putAll(iUaDeptService.getAncestorsNames(deptIds));
            }
            if (param.getArrangeState() == 1) {
                // 已编排
                page.getRecords().forEach(item -> {
                    if (StringUtils.isNotBlank(item.getDept())) {
                        item.setDept(ancestorsNames.get(item.getDept()));
                    }
                    if (StringUtils.isNotBlank(item.getArea())) {
                        String areaFullName = iTaskAreaService.getAreaFullName(param.getTaskId(), item.getArea());
                        if(String.valueOf(SelfArrangeEnum.ARRANGE_BY_LEVEL_ONE.getCode()).equals(level)){
                            areaFullName = areaFullName.substring(0,areaFullName.indexOf("/"));
                        }else if(String.valueOf(SelfArrangeEnum.ARRANGE_BY_LEVEL_TWO.getCode()).equals(level)){
                            areaFullName = areaFullName.substring(0,areaFullName.lastIndexOf("/"));
                        }
                        item.setArea(areaFullName);
                    }
                    // 记录每个批次下有多少个科目
                    Map<String, List<String>> timeMap = new HashMap<>();
                    // 批次科目，如timeId1:subjectId1,timeId1:subjectId2
                    String[] split = item.getTimeSubjectIds().split(",");

                    for (String s : split) {
                        String[] s2 = s.split("#");
                        List<String> subjectArr = timeMap.get(s2[0]);
                        if (subjectArr == null) {
                            subjectArr = new ArrayList<>();
                            subjectArr.add(s2[1]);
                            timeMap.put(s2[0], subjectArr);
                        } else {
                            subjectArr.add(s2[1]);
                        }
                    }

                    // 循环这个考场绑定的批次
                    timeMap.forEach((k, v) -> {
                        ArrangeResultByRoomVO.Time time = new ArrangeResultByRoomVO.Time();
                        time.setTimeId(k);
                        // 一个批次绑定了多少个科目
                        for (String s : v) {
                            ArrangeResultByRoomVO.Time.Subject subject = new ArrangeResultByRoomVO.Time.Subject();
                            Subject sb = iSubjectService.getById(s);
                            subject.setSubjectName(sb.getName());
                            // 考场科目下报考的考生数量
                            int candidateNum = iTimeRoomCandidateService.lambdaQuery()
                                    .eq(TimeRoomCandidate::getTaskId, param.getTaskId())
                                    .eq(TimeRoomCandidate::getTimeId, k)
                                    .eq(TimeRoomCandidate::getRoomId, item.getRoomId())
                                    .eq(TimeRoomCandidate::getSubjectId, s)
                                    .eq(BaseEntity::getDelFlag, false)
                                    .count();
                            subject.setSubjectNum(candidateNum);
                            time.getSubjectList().add(subject);
                        }
                        item.getTimeList().add(time);
                    });
                    item.setTimeSubjectIds(null);
                });
            } else {
                List<Time> timeList = iTimeService.lambdaQuery().eq(Time::getTaskId, param.getTaskId())
                        .eq(BaseEntity::getDelFlag, false).list();
                List<TimeRoom> list = iTimeRoomService.lambdaQuery().eq(TimeRoom::getTaskId, param.getTaskId())
                        .eq(TimeRoom::getSelectType, 1).eq(BaseEntity::getDelFlag, false).list();
                Map<String, List<TimeRoom>> timeRoomGroup = list.stream()
                        .collect(Collectors.groupingBy(TimeRoom::getTimeId));
                List<ArrangeCount> subjectCandidateCountList = iCandidateSubjectService
                        .getSubjectCandidateCount(param.getTaskId());
                Map<String, Integer> subjectCandidateMap = subjectCandidateCountList.stream()
                        .collect(Collectors.toMap(ArrangeCount::getValue, ArrangeCount::getTotal));
                // 未编排
                page.getRecords().forEach(item -> {
                    item.setDept(ancestorsNames.get(item.getDept()));
                    if (StringUtils.isNotBlank(item.getArea())) {
                        String areaFullName = iTaskAreaService.getAreaFullName(param.getTaskId(), item.getArea());
                        if(String.valueOf(SelfArrangeEnum.ARRANGE_BY_LEVEL_ONE.getCode()).equals(level)){
                            areaFullName = areaFullName.substring(0,areaFullName.indexOf("/"));
                        }else if(String.valueOf(SelfArrangeEnum.ARRANGE_BY_LEVEL_TWO.getCode()).equals(level)){
                            areaFullName = areaFullName.substring(0,areaFullName.lastIndexOf("/"));
                        }
                        item.setArea(areaFullName);
                    }
                    timeList.forEach(t -> {
                        List<TimeRoom> timeRooms = timeRoomGroup.get(t.getId());
                        boolean flag = true;
                        if (CollectionUtils.isNotEmpty(timeRooms)) {
                            Optional<TimeRoom> first = timeRooms.stream()
                                    .filter(e -> item.getRoomId().equals(e.getRoomId())).findFirst();
                            flag = !first.isPresent();
                        }
                        if (flag) {
                            ArrangeResultByRoomVO.Time time = new ArrangeResultByRoomVO.Time();
                            time.setTimeId(t.getId());
                            List<TimeSubject> subjects = iTimeSubjectService.lambdaQuery()
                                    .eq(TimeSubject::getTaskId, param.getTaskId()).eq(TimeSubject::getTimeId, t.getId())
                                    .eq(BaseEntity::getDelFlag, false).list();
                            if (CollectionUtils.isNotEmpty(subjects)) {
                                for (TimeSubject s : subjects) {
                                    ArrangeResultByRoomVO.Time.Subject subject = new ArrangeResultByRoomVO.Time.Subject();
                                    subject.setSubjectName(iSubjectService.getById(s.getSubjectId()).getName());
                                    // 考场科目下报考的考生数量
                                    int subjectNum = iTimeRoomCandidateService.lambdaQuery()
                                            .eq(TimeRoomCandidate::getTaskId, param.getTaskId())
                                            .eq(TimeRoomCandidate::getTimeId, t.getId())
                                            .eq(TimeRoomCandidate::getSubjectId, s.getSubjectId())
                                            .eq(BaseEntity::getDelFlag, false).count();
                                    // 总人数
                                    Integer total = subjectCandidateMap.get(s.getSubjectId());
                                    subject.setSubjectNum(total - subjectNum);
                                    if(subject.getSubjectNum() > 0){
                                        time.getSubjectList().add(subject);
                                    }
                                }
                                item.getTimeList().add(time);
                            }
                        }
                    });
                });
            }
        }
        return page;
    }

    @Override
    public Page<ArrangeResultBySubjectVO> searchArrangeResultBySubject(Page<ArrangeResultBySubjectVO> page,
                                                                       ArrangeResultBySubjectParam param) {
        param.setAreaParentIds(iProctorService.getAreasByAreaId(param.getTaskId(), param.getArea()));
        if(StringUtils.isNotBlank(param.getDept())) {
            param.setDeptIds(iProctorService.getAncestorsByDeptId(param.getDept()));
        }
        arrangeMapper.searchArrangeResultBySubject(page, param);
        if (CollectionUtils.isNotEmpty(page.getRecords())) {
            List<String> deptIds = page.getRecords().stream()
                    .filter(s -> StrUtil.isNotBlank(s.getDept())).map(ArrangeResultBySubjectVO::getDept).collect(Collectors.toList());
            Map<String, String> ancestorsNames = new HashMap<>();
            if(deptIds.size() > 0) {
                ancestorsNames.putAll(iUaDeptService.getAncestorsNames(deptIds));
            }

            List<ExamRoomTypeVo> types = iSubjectService.queryExamRoomTYpes();
            //转成map
            Map<String, ExamRoomTypeVo> typeMap = types.stream()
                    .collect(Collectors.toMap(ExamRoomTypeVo::getId, Function.identity(), (k1, k2) -> k1));
            if (param.getArrangeState() == 1) {
                page.getRecords().stream().forEach(item -> {
                    item.setDept(ancestorsNames.get(item.getDept()));
                    item.setRoomNum(item.getSubjectRoomStr().split(",").length);
                    item.setSubjectRoomStr(null);
                    if (StringUtils.isNotBlank(item.getAnswerType())) {
                        ExamRoomTypeVo examRoomTypeVo = typeMap.get(item.getAnswerType());
                        if (examRoomTypeVo != null) {
                            item.setAnswerType(examRoomTypeVo.getTypeName());
                        }
                    }
                });
            } else {
                Integer roomCount = iTaskRoomService.lambdaQuery().eq(TaskRoom::getTaskId, param.getTaskId())
                        .eq(BaseEntity::getDelFlag, false).count();
                page.getRecords().stream().forEach(item -> {
                    item.setDept(ancestorsNames.get(item.getDept()));
                    if (StringUtils.isNotBlank(item.getAnswerType())) {
                        ExamRoomTypeVo examRoomTypeVo = typeMap.get(item.getAnswerType());
                        if (examRoomTypeVo != null) {
                            item.setAnswerType(examRoomTypeVo.getTypeName());
                        }
                    }
                    // 考场数=总考场-已编排考场数-忽略考场数
                    int ignoreNum = iTimeRoomService.lambdaQuery().eq(TimeRoom::getTaskId, param.getTaskId())
                            .eq(BaseEntity::getDelFlag, false)
                            .eq(TimeRoom::getSelectType, 1).eq(TimeRoom::getTimeId, item.getTimeId()).count();
                    int arrangeRoomNum = iTimeRoomCandidateService.lambdaQuery()
                            .eq(TimeRoomCandidate::getTaskId, param.getTaskId())
                            .eq(TimeRoomCandidate::getTimeId, item.getTimeId())
                            .eq(BaseEntity::getDelFlag, false)
                            .groupBy(TimeRoomCandidate::getRoomId)
                            .list().size();

                    item.setRoomNum(roomCount - ignoreNum - arrangeRoomNum);
                    // 考生数
                    item.setCandidateNum(iCandidateSubjectService.lambdaQuery()
                            .eq(CandidateSubject::getTaskId, param.getTaskId())
                            .eq(CandidateSubject::getSubjectId, item.getSubjectId()).eq(BaseEntity::getDelFlag, false)
                            .count());
                    item.setSubjectId(null);
                    item.setTimeId(null);
                });
            }
        }
        return page;
    }

    @Override
    public Page<ArrangeResultByCandidateVO> searchArrangeResultByCandidate(Page<ArrangeResultByCandidateVO> page,
                                                                           ArrangeResultByCandidateParam param) {
        String level = JudgeAreaLevel(param.getTaskId());
        param.setAreaParentIds(iProctorService.getCandidateAreasByAreaId(param.getTaskId(), param.getArea()));
        if(StringUtils.isNotBlank(param.getDept())) {
            param.setDeptIds(iProctorService.getAncestorsByDeptId(param.getDept()));
        }

        arrangeMapper.searchArrangeResultByCandidate(page, param);
        if (CollectionUtils.isNotEmpty(page.getRecords())) {
            List<String> deptIds = page.getRecords().stream()
                    .filter(s -> StringUtils.isNotBlank(s.getDept()))
                    .map(ArrangeResultByCandidateVO::getDept)
                    .collect(Collectors.toList());
            Map<String, String> ancestorsNames = new HashMap<>();
            if(deptIds.size() > 0) {
                ancestorsNames.putAll(iUaDeptService.getAncestorsNames(deptIds));
            }
            // 查询考生区域信息
            Map<String, TaskCandidateArea> mapTaskCandidateArea = iTaskCandidateAreaService.getTaskCandidateArea(param.getTaskId());

            // 查询批次名称
            Map<String, Time> timeNameMap = iTimeService.lambdaQuery().eq(Time::getTaskId, param.getTaskId())
                    .eq(BaseEntity::getDelFlag, false).list().stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));
            // 查询科目名称
            Map<String, String> subjectNameMap = iSubjectService.lambdaQuery().eq(Subject::getTaskId, param.getTaskId())
                    .eq(BaseEntity::getDelFlag, false).list().stream().collect(Collectors.toMap(BaseEntity::getId, Subject::getName));
            //考点名称
            Map<String, String> placeNameMap;
            // 考场名称
            Map<String, String> roomNameMap;
            if(param.getArrangeState() == 1) { // 已编排
                Set<String> placeIdSet = page.getRecords().stream().map(ArrangeResultByCandidateVO::getPlaceName).collect(Collectors.toSet());
                placeNameMap = iTaskPlaceService.lambdaQuery().in(BaseEntity::getId, placeIdSet).list()
                        .stream().collect(Collectors.toMap(BaseEntity::getId, TaskPlace::getName));

                Set<String> roomIdSet = page.getRecords().stream().map(ArrangeResultByCandidateVO::getRoomId).collect(Collectors.toSet());
                roomNameMap = iTaskRoomService.lambdaQuery().in(BaseEntity::getId, roomIdSet).list()
                        .stream().collect(Collectors.toMap(BaseEntity::getId, TaskRoom::getName));
            } else { // 未编排，考生不会绑定考点考场
                placeNameMap = new HashMap<>();
                roomNameMap = new HashMap<>();
            }

            page.getRecords().stream().forEach(item -> {
                item.setDept(ancestorsNames.get(item.getDept()));
                if (StringUtils.isNotBlank(item.getArea())) {
                    String areaFullName = getAreaFullName(item.getArea(), mapTaskCandidateArea);
                    if(String.valueOf(SelfArrangeEnum.ARRANGE_BY_LEVEL_ONE.getCode()).equals(level)){
                        areaFullName = areaFullName.substring(0,areaFullName.indexOf("/"));
                    }else if(String.valueOf(SelfArrangeEnum.ARRANGE_BY_LEVEL_TWO.getCode()).equals(level)){
                        areaFullName = areaFullName.substring(0,areaFullName.lastIndexOf("/"));
                    }
                    item.setArea(areaFullName);
                }
                item.setRoom(roomNameMap.get(item.getRoomId()));
                item.setPlaceName(placeNameMap.get(item.getPlaceName()));
                item.setSubject(subjectNameMap.get(item.getSubjectId()));
                if(StringUtils.isNotBlank(item.getTimeId())) {
                    item.setTimeName(timeNameMap.get(item.getTimeId()).getName());
                    item.setStartTime(timeNameMap.get(item.getTimeId()).getStartTime());
                }
            });
        }
        return page;
    }


    /**
     * 获取地区的完整名称
     *
     * @param areaId
     * @param mapTaskCandidateArea
     * @return
     */
    private String getAreaFullName(String areaId, Map<String, TaskCandidateArea> mapTaskCandidateArea) {
        TaskCandidateArea taskCandidateArea = MapUtil.get(mapTaskCandidateArea, areaId, TaskCandidateArea.class);
        if (taskCandidateArea != null) {
            if (StrUtil.isBlank(taskCandidateArea.getParentIds())) {
                return taskCandidateArea.getName();
            }
            // 获取父类地区IDS
            List<String> parentAreaIds = StrUtil.split(taskCandidateArea.getParentIds(), StrPool.COMMA);
            // 获取父类地区名字拼接
            String currentParentNames = parentAreaIds.stream()
                    .filter(StrUtil::isNotBlank)
                    .map(mapTaskCandidateArea::get)
                    .filter(ObjectUtil::isNotEmpty)
                    .map(TaskCandidateArea::getName)
                    .filter(StrUtil::isNotBlank)
                    .collect(Collectors.joining(StrPool.SLASH));
            if (StrUtil.isNotBlank(currentParentNames)) {
                String areaFullName = currentParentNames + StrPool.SLASH + taskCandidateArea.getName();
                return areaFullName;
            }
        }
        return null;
    }

    @Override
    public ArrangeSubjectCountVO getArrangeSubjectCountResult(String taskId) {
        List<TimeSubject> list = iTimeSubjectService.lambdaQuery().select(BaseEntity::getId)
                .eq(TimeSubject::getTaskId, taskId).eq(BaseEntity::getDelFlag, false).groupBy(TimeSubject::getSubjectId)
                .list();
        List<TimeRoomCandidate> list1 = iTimeRoomCandidateService.lambdaQuery().select(BaseEntity::getId)
                .eq(TimeRoomCandidate::getTaskId, taskId).eq(BaseEntity::getDelFlag, false)
                .groupBy(TimeRoomCandidate::getSubjectId).list();
        List<TimeRoomCandidate> list2 = iTimeRoomCandidateService.lambdaQuery().select(BaseEntity::getId)
                .eq(TimeRoomCandidate::getTaskId, taskId).eq(BaseEntity::getDelFlag, false)
                .groupBy(TimeRoomCandidate::getRoomId).list();
        return ArrangeSubjectCountVO.builder().arrangedSubjectNum(list1.size()).arrangedRoomNum(list2.size())
                .notArrangeSubjectNum(list.size() - list1.size()).build();
    }

    @Override
    public List<ArrangeResultDetailByTimeVO> getArrangeResultDetailByTime(String taskId, String timeId, int type) {
        return arrangeMapper.getArrangeResultDetailByTime(taskId, timeId, type);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void resetArrange(String taskId) {
        ProgressManager.updateProgress(8L);

        Task task = iTaskService.getTaskById(taskId);
        if(task.getPublish()){
            throw new KqException(ResponseCode.TASK_PUBLISH_TRUE.getCode(), "任务已发布，不允许操作此功能。");
        }
        Boolean dataLock = task.getDataLock();
        if (dataLock) {
            throw new KqException(ResponseCode.TASK_DATA_LOCK_TRUE.getCode(), "数据已锁定，不允许操作此功能。");
        }
        ProgressManager.updateProgress(18L);

        iTaskService.lambdaUpdate().set(Task::getDataLock, false).set(Task::getProctorDataLock, false)
                .set(Task::getProctorArrangeType, 0).eq(BaseEntity::getId, taskId).update();
        ProgressManager.updateProgress(33L);

        iTimeRoomCandidateService.lambdaUpdate().set(BaseEntity::getDelFlag, true).eq(TimeRoomCandidate::getTaskId, taskId).eq(BaseEntity::getDelFlag, false).update();

        // 编排方式
        TimeRoomParam one = iTimeRoomParamService.lambdaQuery().eq(TimeRoomParam::getTaskId, taskId)
                .eq(TimeRoomParam::getCode, StringCodeEnum.ARRANGE_PARAM_ARRANGE_TYPE.getCode())
                .eq(BaseEntity::getDelFlag, false).last("limit 1").one();


        if (task != null && TaskExamTypeEnum.ONLINE.getCode().equals(task.getExamType())) {
            // 如果是虚拟考场，则删除考点考场
            if ("0".equals(one.getValue())) {
                iTaskPlaceService.lambdaUpdate().set(BaseEntity::getDelFlag, true).eq(TaskPlace::getTaskId, taskId).eq(BaseEntity::getDelFlag, false).update();
                // 删除考场表
                iTaskRoomService.deleteAllByTaskId(taskId);
            }
            // 清除监考员绑定信息
            iProctorService.resetProctorArrange(taskId);
        }
        ProgressManager.updateProgress(56L);

        iTimeRoomService.lambdaUpdate().eq(TimeRoom::getTaskId, taskId).eq(BaseEntity::getDelFlag, false).remove();
        ProgressManager.updateProgress(80L);

        if ("2".equals(one.getValue())) { // 自定义编排，删除批次绑定的科目
            iTimeSubjectService.lambdaUpdate().set(BaseEntity::getDelFlag, true).eq(TimeSubject::getTaskId, taskId).eq(BaseEntity::getDelFlag, false).update();
        }
        ProgressManager.finish(ProgressResult.builder().success(Boolean.TRUE).build());
    }

    @Override
    public void changRoom(ChangRoomParam param) {
        if (param.getArrangeState() == 0) {
            this.changRoomByNotArrange(param);
        } else {
            this.changRoomByArranged(param);
        }
    }

    /**
     * 未编排的考生指定考场
     *
     * @param param
     */
    private void changRoomByNotArrange(ChangRoomParam param) {
        ProgressManager.updateProgress(8);
        ChangeRoomVO result = ChangeRoomVO.builder().total(param.getCandidateList().size()).build();

        if (CollectionUtils.isNotEmpty(param.getRoomIdList()) && CollectionUtils.isNotEmpty(param.getCandidateList())) {

            ConcurrentLinkedDeque<ChangRoomParam.Candidate> candidateQueue = new ConcurrentLinkedDeque(param.getCandidateList());

            Map<String, TimeRoom> timeRoomMap = new HashMap<>();

            List<TimeRoom> updateTimeRoomList = new ArrayList<>();

            List<TimeRoomCandidate> timeRoomCandidateList = new ArrayList<>();

            Map<String, String> paramMap = iTimeRoomParamService.getTimeRoomParamMap(iTimeRoomParamService.getTaskTimeRoomParam(param.getTaskId()), param.getTaskId());

            Map<String, TimeSubject> timeSubjectMap = new HashMap<>();

            Map<String, Integer> seatNumMap = new HashMap<>();

            ProgressManager.updateProgress(20);

            // 考场开始编排考生
            for (int i = 0; i < param.getRoomIdList().size(); i++) {
                String roomId = param.getRoomIdList().get(i);
                TaskPlace taskPlace = iTaskPlaceService.getTaskByRoomId(param.getTaskId(), roomId);

                // 循环编排考生
                while (true) {
                    if (candidateQueue.isEmpty()) {
                        break;
                    }
                    ChangRoomParam.Candidate candidate = candidateQueue.pop();

                    TimeSubject timeSubject = timeSubjectMap.get(candidate.getSubjectId());
                    if (timeSubject == null) {
                        timeSubject = iTimeSubjectService.lambdaQuery().eq(TimeSubject::getTaskId, param.getTaskId())
                                .eq(TimeSubject::getSubjectId, candidate.getSubjectId()).eq(BaseEntity::getDelFlag, false).one();
                        timeSubjectMap.put(candidate.getSubjectId(), timeSubject);
                    }

                    if(iTimeRoomCandidateService.lambdaQuery().eq(TimeRoomCandidate::getTaskId, param.getTaskId())
                            .eq(TimeRoomCandidate::getTimeId, timeSubject.getTimeId()).eq(TimeRoomCandidate::getCandidateId, candidate.getCandidateId())
                            .eq(BaseEntity::getDelFlag, false).count() > 0){
                        // 同批次 同考生 限制只能报一个科目
                        continue;
                    }

                    String key = timeSubject.getTimeId() + "_" + roomId;
                    TimeRoom timeRoom = timeRoomMap.get(key);
                    if (timeRoom == null) {
                        timeRoom = iTimeRoomService.lambdaQuery().select(BaseEntity::getId, TimeRoom::getActualCount, TimeRoom::getPlanCount, TimeRoom::getMaxCount)
                                .eq(TimeRoom::getTaskId, param.getTaskId()).eq(TimeRoom::getTimeId, timeSubject.getTimeId())
                                .eq(TimeRoom::getRoomId, roomId).eq(BaseEntity::getDelFlag, false).one();
                        // 该批次没有考场可以使用
                        if(timeRoom == null) {
                            continue;
                        }
                        timeRoomMap.put(key, timeRoom);
                    }

                    String seatKey = StringUtils.joinWith("_", param.getTaskId(), timeSubject.getTimeId(), roomId);
                    Integer maxSeat = seatNumMap.get(seatKey);
                    if(maxSeat == null) {
                        maxSeat = timeRoomCandidateMapper.getMaxSeatNum(param.getTaskId(), timeSubject.getTimeId(), roomId);
                        if(maxSeat == null) {
                            maxSeat = 0;
                        }
                    }
                    ++maxSeat;
                    seatNumMap.put(seatKey, maxSeat);
                    // 生成准考证
                    String zkz = admissionService.getAdmissionNumber(param.getTaskId(), paramMap, TaskPlaceVO.builder()
                            .province(StringUtils.isBlank(taskPlace.getProvince()) ? "10" : taskPlace.getProvince())
                            .city(StringUtils.isBlank(taskPlace.getCity()) ? "01" : taskPlace.getCity())
                            .district(StringUtils.isBlank(taskPlace.getDistrict()) ? "01" : taskPlace.getDistrict()).build());

                    int admissionType = Integer.parseInt(String.valueOf(paramMap.get("admissionType")));
                    if(admissionType == ArrangeParamCodeEnum.ADMISSION_TYPE_CUSTOM.getCode().intValue()){
                        Optional<CustomArrange> optional = iCustomArrangeService.getByCandidateId(param.getTaskId(), candidate.getCandidateId());
                        zkz =  optional.map(CustomArrange::getAdmissionNumber)
                                // 当前考生暂无准考证号，请录入考生准考证号，或使用其他准考证号生成方式
                                .orElseThrow(() -> new KqException(ResponseCode.MANUAL_ARRANGE_ADMISSION_NUMBER_NOT_FOUND.getCode(),
                                        ResponseCode.MANUAL_ARRANGE_ADMISSION_NUMBER_NOT_FOUND.getMsg()));
                    }
                    // 未编排考生，新编排
                    TimeRoomCandidate timeRoomCandidate = new TimeRoomCandidate();
                    timeRoomCandidate.setCandidateId(candidate.getCandidateId())
                            .setTaskId(param.getTaskId())
                            .setRoomId(roomId)
                            .setPlaceId(taskPlace.getId())
                            .setTimeRoomId(timeRoom.getId())
                            .setTimeId(timeSubject.getTimeId())
                            .setPlaceId(taskPlace.getId())
                            .setSubjectId(candidate.getSubjectId())
                            .setSeatNum(StringUtil.stringFormatZero(maxSeat, 3))
                            .setCandidateSubjectId(candidate.getId())
                            .setAdmissionNum(zkz);
                    timeRoomCandidateList.add(timeRoomCandidate);

                    timeRoom.setActualCount(timeRoom.getActualCount() + 1);
                    updateTimeRoomList.add(timeRoom);

                    result.setArrangeNum(result.getArrangeNum() + 1);

                    if (timeRoom.getActualCount() >= timeRoom.getMaxCount() || candidateQueue.isEmpty()) {
                        break;
                    }
                }

                ProgressManager.stepProgressCurrent(i, param.getRoomIdList().size(), 20, 90, null);
            }

            result.setNotArrangeNum(param.getCandidateList().size() - result.getArrangeNum());

            if (timeRoomCandidateList.size() > 0) {
                iTimeRoomCandidateService.saveOrUpdateBatch(timeRoomCandidateList);
                iTimeRoomService.updateBatchById(updateTimeRoomList);
            }
        }

        ProgressManager.finish(ProgressResult.builder().success(Boolean.TRUE).result(result).build());
    }

    /**
     * 已编排考生调换考场
     *
     * @param param
     */
    private void changRoomByArranged(ChangRoomParam param) {
        ProgressManager.updateProgress(8L);

        ConcurrentLinkedDeque<ChangRoomParam.Candidate> candidateQueue = new ConcurrentLinkedDeque(param.getCandidateList());

        List<TimeRoom> updateTimeRoomList = new ArrayList<>();
        List<TimeRoomCandidate> timeRoomCandidateList = new ArrayList<>();
        ChangeRoomVO result = ChangeRoomVO.builder().total(param.getCandidateList().size()).build();

        // 考场开始编排考生
        for (int i = 0; i < param.getRoomIdList().size(); i++) {
            String roomId = param.getRoomIdList().get(i);

            TimeRoom timeRoom = iTimeRoomService.lambdaQuery().select(BaseEntity::getId, TimeRoom::getActualCount, TimeRoom::getPlanCount, TimeRoom::getMaxCount)
                    .eq(TimeRoom::getTaskId, param.getTaskId()).eq(TimeRoom::getTimeId, param.getTimeId())
                    .eq(TimeRoom::getRoomId, roomId).eq(BaseEntity::getDelFlag, false).one();
            if (timeRoom != null) {
                Integer maxSeatNum = timeRoomCandidateMapper.getMaxSeatNum(param.getTaskId(), param.getTimeId(), roomId);
                maxSeatNum = maxSeatNum == null ? 1 : maxSeatNum + 1;

                boolean continueForEach = true;

                // 直到考生队列中没有考生为止
                while (continueForEach) {
                    if (timeRoom.getActualCount() >= timeRoom.getMaxCount() || candidateQueue.isEmpty()) {
                        break;
                    }

                    ChangRoomParam.Candidate candidate = candidateQueue.pop();

                    // 已编排考生，交换考场
                    if (!roomId.equalsIgnoreCase(candidate.getRoomId())) {
                        // 原编排信息
                        TimeRoomCandidate timeRoomCandidate = TimeRoomCandidate.builder().build();
                        timeRoomCandidate.setId(candidate.getId());
                        // 不同考场交换，同考场不处理，考生不再编排
                        timeRoomCandidate.setRoomId(roomId);
                        timeRoomCandidate.setTimeRoomId(timeRoom.getId());
                        timeRoomCandidate.setSeatNum(StringUtil.stringFormatZero(maxSeatNum++, 3));
                        timeRoom.setActualCount(timeRoom.getActualCount() + 1);

                        // 记录已编排人数
                        result.setArrangeNum(result.getArrangeNum() + 1);

                        updateTimeRoomList.add(timeRoom);
                        timeRoomCandidateList.add(timeRoomCandidate);
                    } else {
                        result.setNotArrangeNum(result.getNotArrangeNum() + 1);
                    }
                    if (timeRoom.getActualCount() >= timeRoom.getMaxCount() || candidateQueue.isEmpty()) {
                        break;
                    }
                }
            }
            result.setNotArrangeNum(result.getNotArrangeNum() + candidateQueue.size());
            ProgressManager.stepProgressCurrent(i, param.getRoomIdList().size(), 20, 90, null);
        }
        if (timeRoomCandidateList.size() > 0) {
            iTimeRoomCandidateService.saveOrUpdateBatch(timeRoomCandidateList);
            iTimeRoomService.updateBatchById(updateTimeRoomList);
        }
        ProgressManager.finish(ProgressResult.builder().success(Boolean.TRUE).result(result).build());
    }

    @Override
    public GovPage<PlaceRoomVO> getChangeRoom(GovPage<PlaceRoomVO> page, SearchChangeRoomParam param) {
        iTaskService.isPublishAndDataLockThrowException(param.getTaskId());
        arrangeMapper.getChangeRoom(page, param);
        if (CollectionUtils.isNotEmpty(page.getRecords())) {
            List<String> deptIds = page.getRecords().stream()
                    .filter(s -> Objects.nonNull(s.getDept())).map(PlaceRoomVO::getDept).collect(Collectors.toList());
            Map<String, String> ancestorsNames = new HashMap<>();
            if(deptIds.size() > 0) {
                ancestorsNames.putAll(iUaDeptService.getAncestorsNames(deptIds));
            }
            page.getRecords().stream().forEach(item -> {
                item.setDept(ancestorsNames.get(item.getDept()));
                if (StringUtils.isNotBlank(item.getArea())) {
                    item.setArea(iTaskAreaService.getAreaFullName(param.getTaskId(), item.getArea()));
                }
            });
        }
        return page;
    }

    private File exportArrangeResultByCandidate(String taskId){

        List<ExportArrangeResultVO> list = arrangeMapper.exportArrangeResultByCandidate(taskId);
        File file = null;
        if(CollectionUtil.isNotEmpty(list)){
            // 查询批次名称
            Map<String, Time> timeMap = iTimeService.lambdaQuery().eq(Time::getTaskId, taskId)
                    .eq(BaseEntity::getDelFlag, false).list().stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));

            Map<String, TaskPlace> placeMap = iTaskPlaceService.lambdaQuery().eq(TaskPlace::getTaskId, taskId)
                    .eq(BaseEntity::getDelFlag, false).list().stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));

            Map<String, TaskRoom> roomMap = iTaskRoomService.lambdaQuery().eq(TaskRoom::getTaskId, taskId)
                    .eq(BaseEntity::getDelFlag, false).list().stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));

            Map<String, Subject> subjectMap = iSubjectService.lambdaQuery().eq(Subject::getTaskId, taskId)
                    .eq(BaseEntity::getDelFlag, false).list().stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));

            Map<String, TaskArea> areaMap = iTaskAreaService.getTaskAreaMap(taskId);
            file = FileUtil.createTempFile(taskId,".dbf",true);
            try {
                DBFField[] bmkDbf = arrangedResultExportUtil.getBmkDBFField();
                DBFWriter writer = new DBFWriter(file, Charset.forName("GBK"));
                writer.setFields(bmkDbf);
                list.stream().forEach(c -> {
                    Time time = timeMap.get(c.getTimeId());
                    TaskRoom room = roomMap.get(c.getRoomId());
                    TaskPlace place = placeMap.get(c.getPlaceId());
                    Subject subject = subjectMap.get(c.getSubjectId());
                    Object[] data = new Object[bmkDbf.length];
                    data[0] = c.getAdmissionNumber();
                    data[1] = c.getCandidateName();
                    data[2] = c.getSex();
                    if(ObjectUtil.isNotEmpty(room)){
                        data[3] = String.valueOf(room.getCode().intValue());
                        data[4] = room.getName();
                    }
                    if(ObjectUtil.isNotEmpty(place)){
                        data[5] = String.valueOf(place.getCode().intValue());
                        data[6] = place.getName();
                        if(StrUtil.isNotBlank(place.getProvince()) && ObjectUtil.isNotEmpty(areaMap.get(place.getProvince())) ){
                            data[7] = areaMap.get(place.getProvince()).getAreaId();
                            data[8] = areaMap.get(place.getProvince()).getName();
                        }
                        if(StrUtil.isNotBlank(place.getCity()) && ObjectUtil.isNotEmpty(areaMap.get(place.getCity())) ){
                            data[9] = areaMap.get(place.getCity()).getAreaId();
                            data[10] = areaMap.get(place.getCity()).getName();
                        }
                        if(StrUtil.isNotBlank(place.getDistrict()) && ObjectUtil.isNotEmpty(areaMap.get(place.getDistrict())) ){
                            data[11] = areaMap.get(place.getDistrict()).getAreaId();
                            data[12] = areaMap.get(place.getDistrict()).getName();
                        }
                    }
                    if(ObjectUtil.isNotEmpty(subject)){
                        data[13] = subject.getCode();
                        data[14] = subject.getName();
                    }
                    if(ObjectUtil.isNotEmpty(time)){
                        data[15] = String.valueOf(time.getCode().intValue());
                        data[16] = time.getName();
                    }
                    data[17] = c.getSeat();
                    data[18] = String.valueOf(CodeEnum.YZ_HAN.getCode().intValue());//1 语种 汉语
                    data[19] = String.valueOf(CodeEnum.TSRQ_NO.getCode().intValue());//0 非特殊人群
                    data[20] = c.getCardNumber();
                    data[21] = "000";
                    data[22] = String.valueOf(CodeEnum.COMPUTER_EXAM.getCode().intValue());//电子作答
                    writer.addRecord(data);
                });
                writer.close();
                return file;
            } catch (Exception ex){
                boolean flag = file.delete();
                if(!flag){
                    log.error("文件删除失败");
                }
                ex.printStackTrace();
                throw new KqException(ResponseCode.ERROR_CREATE_BMK_DBF.getCode(), "生成dbf文件失败");
            }
        } else{
            throw new KqException(ResponseCode.NOT_EXIST_BMK_DBF.getCode(), "没有批次数据，无法导出");
        }
    }

    public void downloadPackage(String taskId) throws Exception {
        List<ExamResultMonitor> list = iExamResultMonitorService.lambdaQuery()
                .eq(ExamResultMonitor::getTaskId, taskId).eq(BaseEntity::getDelFlag, false).isNotNull(ExamResultMonitor::getPath).list();
        Task task = iTaskService.getTaskById(taskId);
        ProgressManager.updateProgressCurrent(10L, "查询数据成功");
        File subjectFile = iSubjectService.createXml(taskId);
        ProgressManager.updateProgressCurrent(30L, "生成科目文件成功");
        File timeFile = iTimeService.exportTime(taskId);
        ProgressManager.updateProgressCurrent(50L, "生成批次文件成功");
        File candidateFile = this.exportArrangeResultByCandidate(taskId);
        ProgressManager.updateProgressCurrent(70L, "生成报名文件成功");
        File tempFile = FileUtil.createTempFile(task.getName(),".zip", true);

        if(CollectionUtil.isNotEmpty(list)){
            ZipOutputStream  zipOutputStream = null;
            InputStream inputStream = null;
            InputStream subjectInputStream = null;
            InputStream timeInputStream = null;
            InputStream candidateInputStream = null;
            try{
                zipOutputStream  = new ZipOutputStream(new FileOutputStream(tempFile));
                for(int i = 0 ; i < list.size(); i++) {
                    ExamResultMonitor c = list.get(i);
                    String prefix = c.getPackageName().substring(0, c.getPackageName().lastIndexOf("."));
                    File file = FileUtil.createTempFile(prefix, "." + c.getPackageType(), true);
                    HttpUtil.downFile(configManager.getHuaweiCloudObsPath() + "/" + c.getPath(), file.getPath());
                    inputStream = FileUtil.getInputStream(file);
                    ZipEntry entry = new ZipEntry(prefix + "." + c.getPackageType());
                    zipOutputStream.putNextEntry(entry);
                    IoUtil.copy(inputStream, zipOutputStream);
                    boolean flag = file.delete();
                    if(!flag){
                        log.error("删除答案包临时文件失败");
                    }
                }

                if(subjectFile != null){
                    subjectInputStream = FileUtil.getInputStream(subjectFile);
                    ZipEntry entry = new ZipEntry("subject_"+subjectFile.getName());
                    zipOutputStream.putNextEntry(entry);
                    IoUtil.copy(subjectInputStream, zipOutputStream);
                }


                if(timeFile != null){
                    timeInputStream = FileUtil.getInputStream(timeFile);
                    ZipEntry entry = new ZipEntry("time_"+timeFile.getName());
                    zipOutputStream.putNextEntry(entry);
                    IoUtil.copy(timeInputStream, zipOutputStream);
                }


                if(candidateFile != null){
                    candidateInputStream = FileUtil.getInputStream(candidateFile);
                    ZipEntry entry = new ZipEntry("bmk_"+candidateFile.getName());
                    zipOutputStream.putNextEntry(entry);
                    IoUtil.copy(candidateInputStream, zipOutputStream);
                }
                    zipOutputStream.flush();
            }catch (Exception ex){
                log.error("下载文件失败",ex);
            } finally {
                if(timeFile != null){
                    boolean timeFlag = timeFile.delete();
                    if(!timeFlag){
                        log.error("删除批次临时文件失败");
                    }
                }
                if(subjectFile != null){
                    boolean subjectFlag = subjectFile.delete();
                    if(!subjectFlag){
                        log.error("删除科目文件失败");
                    }
                }
                if(candidateFile != null){
                    boolean candidateFlag = candidateFile.delete();
                    if(!candidateFlag){
                        log.error("删除考生临时文件失败");
                    }
                }
                IoUtil.close(inputStream);
                IoUtil.close(timeInputStream);
                IoUtil.close(subjectInputStream);
                IoUtil.close(candidateInputStream);
                IoUtil.close(zipOutputStream);
            }
        }
        String path = "hz/"+task.getId()+"/"+tempFile.getName();
        String fileUrl = cloudObsService.updateFile(path, tempFile);
        ProgressManager.updateProgressCurrent(90L, "上传桌贴zip包成功");

        if(StrUtil.isNotBlank(fileUrl)){
            ProgressManager.finish(ProgressResult.builder().success(Boolean.TRUE).result(fileUrl).build());
        }else{
            ProgressManager.finish(ProgressResult.builder().success(Boolean.FALSE).result("下载失败").build());
        }

    }

}
